﻿using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace StudentManagementSystem.Helpers
{
    public class  ArrayModelBinder : IModelBinder
    {
        /// <summary>
        /// 在 ASP.NET Core 中，当你通过 HTTP 请求（比如 GET、POST）接收数据时
        /// 框架需要把请求中的数据（如查询字符串、表单、JSON 等）转换成 C# 对象，这个过程叫做 模型绑定（Model Binding）
        /// </summary>
        /// <param name="bindingContext"></param>
        /// <returns></returns>
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            //检查要绑定的模型是否是可枚举类型（如数组、列表等）
            if (!bindingContext.ModelMetadata.IsEnumerableType)
            {
                bindingContext.Result = ModelBindingResult.Failed();
                return Task.CompletedTask;
            }
            // 获取传入的值，比如查询字符串或表单中的值
            var valueProviderResult = bindingContext.ValueProvider
                .GetValue(bindingContext.ModelName);
            var value = valueProviderResult.FirstValue;

            if (string.IsNullOrWhiteSpace(value))
            {
                bindingContext.Result = ModelBindingResult.Success(null);
                return Task.CompletedTask;
            }

            //获取元素类型
            var elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
            //获取类型转换器
            var converter = TypeDescriptor.GetConverter(elementType);
            //分割字符串并转换
            //将字符串按逗号分割
            //对每个分割后的字符串进行转换
            //例如："1,2,3"-> ["1", "2", "3"]-> [1, 2, 3]
            var values = value.Split(separator: new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => converter.ConvertFromString(text: x.Trim()))
                .ToArray();
            //创建并填充数组
            //将绑定后的数组设置到模型上下文中
            //设置绑定结果为成功
            var typedValues = Array.CreateInstance(elementType, values.Length);
            values.CopyTo(typedValues, index: 0);
            bindingContext.Model = typedValues;
            bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
            return Task.CompletedTask;
        }

    }
}
